package xyz.jiang.common.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtils {

    private static RedisTemplate<String, Object> redisTemplate;

    @Autowired
    public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
        RedisUtils.redisTemplate = redisTemplate;
    }

    /**
     * 删除一个或多个key
     * @param keys 要删除的key列表
     * @return 成功删除的key数量
     */
    public static Long delete(String... keys) {
        return redisTemplate.delete(Arrays.asList(keys));
    }

    /**
     * 判断key是否存在
     * @param key 键
     * @return true存在，false不存在
     */
    public static Boolean exists(String key) {
        return redisTemplate.hasKey(key);
    }

    /**
     * 设置过期时间
     * @param key 键
     * @param timeout 时间
     * @param unit 时间单位
     * @return true成功，false失败
     */
    public static Boolean expire(String key, long timeout, TimeUnit unit) {
        return redisTemplate.expire(key, timeout, unit);
    }

    public static Boolean setExpireSeconds(String key, long timeout) {
        return redisTemplate.expire(key, timeout, TimeUnit.SECONDS);
    }

    /**
     * 获取key的剩余生存时间
     * @param key 键
     * @return 剩余时间（单位：秒）
     */
    public static Long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 获取key的类型
     * @param key 键
     * @return 数据类型
     */
    public static DataType type(String key) {
        return redisTemplate.type(key);
    }

    // ============================== String 操作 ==============================

    /**
     * 设置字符串值
     * @param key 键
     * @param value 值
     */
    public static void set(String key, Object value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public static void set(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    /**
     * 设置带过期时间的字符串值
     * @param key 键
     * @param value 值
     * @param timeout 过期时间
     * @param unit 时间单位
     */
    public static void setEx(String key, Object value, long timeout, TimeUnit unit) {
        redisTemplate.opsForValue().set(key, value, timeout, unit);
    }

    public static void setEx(String key, Object value, long timeout) {
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    /**
     * 如果不存在则设置（原子操作）
     * @param key 键
     * @param value 值
     * @return true设置成功，false已存在
     */
    public static Boolean setIfAbsent(String key, Object value) {
        return redisTemplate.opsForValue().setIfAbsent(key, value);
    }

    /**
     * 获取字符串值
     * @param key 键
     * @return 值
     */
    public static Object get(String key) {
        return redisTemplate.opsForValue().get(key);
    }

    /**
     * 获取并设置新值（原子操作）
     * @param key 键
     * @param newValue 新值
     * @return 旧值
     */
    public static Object getAndSet(String key, Object newValue) {
        return redisTemplate.opsForValue().getAndSet(key, newValue);
    }

    // ============================== Hash 操作 ==============================

    /**
     * 设置Hash字段值
     * @param key 键
     * @param hashKey 字段名
     * @param value 值
     */
    public static void hSet(String key, String hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    /**
     * 获取Hash字段值
     * @param key 键
     * @param hashKey 字段名
     * @return 值
     */
    public static Object hGet(String key, String hashKey) {
        return redisTemplate.opsForHash().get(key, hashKey);
    }

    /**
     * 获取整个Hash
     * @param key 键
     * @return Map结构数据
     */
    public static Map<Object, Object> hGetAll(String key) {
        return redisTemplate.opsForHash().entries(key);
    }

    // ============================== List 操作 ==============================

    /**
     * 左端插入元素
     * @param key 键
     * @param values 要插入的值
     * @return 插入后列表长度
     */
    public static Long lPush(String key, Object... values) {
        return redisTemplate.opsForList().leftPushAll(key, values);
    }

    /**
     * 获取列表范围
     * @param key 键
     * @param start 开始索引
     * @param end 结束索引
     * @return 元素列表
     */
    public static List<Object> lRange(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    // ============================== Set 操作 ==============================

    /**
     * 添加元素到集合
     * @param key 键
     * @param values 值列表
     * @return 成功添加的数量
     */
    public static Long sAdd(String key, Object... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    /**
     * 获取集合所有元素
     * @param key 键
     * @return 元素集合
     */
    public static Set<Object> sMembers(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    // ============================== ZSet 操作 ==============================

    /**
     * 添加元素到有序集合
     * @param key 键
     * @param value 值
     * @param score 分数
     * @return 是否成功
     */
    public static Boolean zAdd(String key, Object value, double score) {
        return redisTemplate.opsForZSet().add(key, value, score);
    }

    /**
     * 获取范围元素（按分数排序）
     * @param key 键
     * @param start 开始排名
     * @param end 结束排名
     * @return 元素集合
     */
    public static Set<Object> zRange(String key, long start, long end) {
        return redisTemplate.opsForZSet().range(key, start, end);
    }



    /**
     * 模糊查询key
     * @param pattern 匹配模式（如 "user:*"）
     * @return 匹配的key集合
     */
    public static Set<String> keys(String pattern) {
        return redisTemplate.keys(pattern);
    }

    /**
     * 安全反序列化（带类型转换）
     * @param key 键
     * @param type 目标类型
     * @return 转换后的对象
     */
    public static <T> T getObject(String key, Class<T> type) {
        Object value = get(key);
        return type.isInstance(value) ? type.cast(value) : null;
    }

    public static Long increment(String key) {
        return redisTemplate.opsForValue().increment(key, 1);
    }

    public static Long increment(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 对浮点类型值进行原子递增（浮点型）
     * @param key 键
     * @param delta 增量（支持小数）
     * @return 递增后的值
     */
    public static Double increment(String key, double delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    // ============================== 原子减少操作 ==============================

    public static Long decrement(String key) {
        return redisTemplate.opsForValue().increment(key, -1);
    }

    /**
     * 对整数类型值进行原子递减（整型）
     * @param key 键
     * @param delta 减量（必须为整数）
     * @return 递减后的值
     */
    public static Long decrement(String key, long delta) {
        return redisTemplate.opsForValue().increment(key, -delta);
    }

    /**
     * 对浮点类型值进行原子递减（浮点型）
     * @param key 键
     * @param delta 减量（支持小数）
     * @return 递减后的值
     */
    public static Double decrement(String key, double delta) {
        return redisTemplate.opsForValue().increment(key, -delta);
    }

}
